<?php

class Fn
{
    /**
     *  格式化时间
     * @param int    $time      时间戳
     * @param string $separator 分隔 '10'和'分钟前'   eg: '10分钟前'=>'10 分钟前'
     * @return string
     *                          modfify by zengyichao 2013.09.29
     */
    public static function humanTime1($time, $separator = '')
    {
        $dur = time() - $time;
        if ($dur < 60) {
            return '刚刚';
        }
        elseif ($dur < 3600) {
            return floor($dur / 60) . $separator . '分钟前';
        }
        elseif ($time > mktime(0, 0, 0)) {
            return '今天' . $separator . date('H:i', $time);
        }
        elseif ($time > mktime(0, 0, 0) - 86400) {
            return '昨天' . $separator . date('H:i', $time);
        }
        elseif ($time > mktime(0, 0, 0) - 172800) {
            return '前天' . $separator . date('H:i', $time);
        }
        elseif ($time > mktime(0, 0, 0, 1, 1, date('Y'))) {
            return date('m-d H:i', $time);
        }
        else {
            return date('Y-m-d', $time);
        }
    }
    
    /**
     *  格式化时间
     * @param int    $time      时间戳
     * @param string $separator 分隔 '10'和'分钟前'   eg: '10分钟前'=>'10 分钟前'
     * @return string
     */
    public static function humanTime2($time, $separator = '')
    {
        $dur = time() - $time;
        if ($time > mktime(0, 0, 0)) {
            return '今天' . $separator . date('H:i', $time);
        }
        elseif ($time > mktime(0, 0, 0) - 86400) {
            return '昨天' . $separator . date('H:i', $time);
        }
        elseif ($time > mktime(0, 0, 0) - 172800) {
            return '前天' . $separator . date('H:i', $time);
        }
        elseif ($time > mktime(0, 0, 0, 1, 1, date('Y'))) {
            return date('m-d H:i', $time);
        }
        else {
            return date('Y-m-d', $time);
        }
    }
    
    public static function formatTime($time)
    {
        //获取今天凌晨的时间戳
        $day = strtotime(date('Y-m-d', time()));
        //获取昨天凌晨的时间戳
        $pday = strtotime(date('Y-m-d', strtotime('-1 day')));
        //获取现在的时间戳
        $nowtime = time();
        
        $tc = $nowtime - $time;
        if ($time < $pday) {
            $str = date('y/m/d', $time);
        }
        elseif ($time < $day && $time > $pday) {
            $str = "昨天";
        }
        elseif ($tc > 60 * 60) {
            $str = floor($tc / (60 * 60)) . "小时前";
        }
        elseif ($tc > 60) {
            $str = floor($tc / 60) . "分钟前";
        }
        else {
            $str = "刚刚";
        }
        
        return $str;
    }
    
    public static function humanTimeScope($scope, $tmp = '', $delimiter = ':', $hourlimiter = ':', $secondlimiter = '')
    {
        $humanTimeScope = '';
        switch ($tmp) {
            case '':
            default :
                if ($scope > 3600) {
                    $humanTimeScope .= floor($scope / 3600) . $hourlimiter;
                    $scope          %= 3600;
                }
                if ($scope > 60) {
                    $humanTimeScope .= floor($scope / 60) . $delimiter;
                    $scope          %= 60;
                }
                if ($scope > 0) {
                    $humanTimeScope .= $scope . $secondlimiter;
                }
                
                return $humanTimeScope;
                break;
        }
    }
    
    public static function humanTimeDifference($timestamp)
    {
        $interval   = $timestamp - time();
        $timeString = '';
        if ($interval < 0) {
            $timeString = '';
        }
        elseif ($interval < 60 * 60) {
            $minutes    = (int)floor($interval / 60);
            $timeString = $minutes . "分钟";
        }
        elseif ($interval < 24 * 60 * 60) {
            $hours      = (int)floor($interval / 60 / 60);
            $timeString = $hours . "小时";
        }
        else {
            $hours      = (int)floor($interval / (24 * 60 * 60)) + 1;
            $timeString = $hours . "天";
        }
        
        return $timeString;
    }
    
    public static function humanTimeDifference4View($timestamp)
    {
        $interval   = $timestamp - time();
        $timeString = array();
        if ($interval < 0) {
            $timeString = array();
        }
        elseif ($interval < 60 * 60) {
            $timeString['DateTime']  = (int)floor($interval / 60);
            $timeString['time_desc'] = "分钟";
        }
        elseif ($interval < 24 * 60 * 60) {
            $timeString['DateTime']  = (int)floor($interval / 60 / 60);
            $timeString['time_desc'] = "小时";
        }
        else {
            $timeString['DateTime']  = (int)floor($interval / (24 * 60 * 60)) + 1;
            $timeString['time_desc'] = "天";
        }
        
        return $timeString;
    }
    
    public static function howFarAway($timestamp)
    {
        $interval = time() - $timestamp;
        if ($interval < 0) return 0;
        
        return (int)floor($interval / (24 * 60 * 60)) + 1;
    }
    
    public static function humanTime($scope, $delimiter = ':', $hourlimiter = ':')
    {
        $humanTimeScope = 0;
        // if ($scope>3600){
        //     $humanTimeScope .= floor($scope/3600).$hourlimiter;
        //     $scope %= 3600;
        // }
        if ($scope > 60) {
            $humanTimeScope .= floor($scope / 60) . $delimiter;
            $scope          %= 60;
        }
        
        return $humanTimeScope;
//        break;
    }
    
    public static function isJson($str)
    {
        $jsonStr = json_decode($str, true);
        
        return is_null($jsonStr) ? false : $jsonStr;
    }
    
    public static function model($class, $pk)
    {
        $model = new $class;
        
        return $model->findByPk($pk);
    }
    
    public static function pickout($arr, $key, $value)
    {
        if (!is_array($arr)) {
            return false;
        }
        
        foreach ($arr as $aItem) {
            if (isset($aItem[$key]) && ($aItem[$key] == $value)) {
                return $aItem;
            }
        }
        
        return false;
    }
    
    public static function removeByVal($arr, $val)
    {
        $_arr = array();
        foreach ($arr as $aItem) {
            if ($aItem == $val) {
                continue;
            }
            else {
                $_arr[] = $aItem;
            }
        }
        
        return $_arr;
    }
    
    public static function curl($url, $postFields = null, $isSSL = true)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        
        if (is_array($postFields) && 0 < count($postFields)) {
            $postBodyString = "";
            foreach ($postFields as $k => $v) {
                $postBodyString .= "$k=" . urlencode($v) . "&";
            }
            unset($k, $v);
            if ($isSSL) {
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            }
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
        }
        $reponse = curl_exec($ch);
        if (curl_errno($ch)) {
            throw new \yii\base\Exception(curl_error($ch), 0);
        }
        else {
            $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if (200 !== $httpStatusCode) {
                throw new \yii\base\Exception($reponse, $httpStatusCode);
            }
        }
        curl_close($ch);
        
        return $reponse;
    }
    
    /**
     * 从给定关联数组(map)中，按照指定的key和它可能的值，获取需要的字段的值
     * @param array  $items
     * @param string $byKey
     * @param array  $byVal
     * @param string $getKey
     * @return type
     */
    public static function getAttrs($items, $byKey, $byVal, $getKey)
    {
        $result = array();
        foreach ($items as $key => $aItem) {
            if (in_array($aItem[$byKey], $byVal)) {
                $result[] = $aItem[$getKey];
            }
        }
        
        return $result;
    }
    
    /**
     * 获取model的所有数据，结果以数组形式返回
     * @param string $modelName
     * @param string $pk 主键字段，如果设置了，结果返回关联数组，否则返回普通数组
     */
    public static function loadItems($modelName, $pk = '')
    {
        $result   = array();
        $model    = new $modelName;
        $models   = $model->findAll();
        $filedArr = array_keys($model->attributes);
        
        foreach ($models as $aModel) {
            $tmp = array();
            foreach ($filedArr as $aField) {
                $tmp[$aField] = $aModel[$aField];
            }
            if (!$pk) {
                $result[] = $tmp;
            }
            else {
                $pkVal          = $tmp[$pk];
                $result[$pkVal] = $tmp;
            }
        }
        
        return $result;
    }
    
    /**
     * @param string $name model名称
     * @param array  $attr array属性数组
     * @return mixed
     */
    public static function modelFind($name, $attr)
    {
        $model = new $name;
        $model = $model->findByAttributes($attr);
        
        return $model;
    }
    
    public static function mmkDir($newPath)
    {
        if (!is_dir($newPath)) {
            $old = umask(0);
            $ok  = mkdir($newPath, 0777, true);
            umask($old);
        }
    }
    
    public static function replaceUserName($userName)
    {
        mb_internal_encoding("UTF-8");
        $nickLength = mb_strlen($userName);
        $newNick    = "";
        
        $end   = 0;
        $start = 0;
        if ($nickLength <= 4) {
            $start = 1;
            $end   = $nickLength - 1;
        }
        else if ($nickLength > 4) {
            $start = floor($nickLength / 2);
            $end   = $nickLength - 2;
        }
        if ($end > $start) {
            for ($i = 0; $i < $nickLength; $i++) {
                $word = mb_substr($userName, $i, 1);
                if ($i >= $start && $i < $end) {
                    $newNick .= "*";
                }
                else {
                    $newNick .= $word;
                }
            }
        }
        if ($nickLength == 2) {
            $newNick = mb_substr($userName, 0, 1) . "***";
        }
        
        return $newNick;
    }
    
    public static function cutAddress($address)
    {
        mb_internal_encoding("UTF-8");
        $addressLen = mb_strlen($address);
        $length     = $addressLen - ceil($addressLen * 0.3);
        $result     = '';
        
        if ($addressLen == 1) {
            $result = $address . "*****";
        }
        else {
            $result = mb_substr($address, 0, $length) . "*****";
        }
        
        return $result;
    }
    
    public static function utf8Len($str)
    {
        mb_internal_encoding("UTF-8");
        
        return mb_strlen($str);
    }
    
    public static function jsonEncode($array)
    {
        echo json_encode($array);
        exit;
        Yii::$app->end();
    }
    
    public static function model2Array($model, $fields = false)
    {
        $result = array();
        if (!$fields) {
            $fields = array_keys($model->attributes);
        }
        foreach ($fields as $aField) {
            if (isset($model[$aField])) {
                $result[$aField] = $model[$aField];
            }
            elseif ($model[$aField] == null) {
                $result[$aField] = "";
            }
        }
        
        return $result;
    }
    
    public static function models2Array($models)
    {
        $result = array();
        foreach ($models as $aModel) {
            $arr      = self::model2array($aModel);
            $result[] = $arr;
        }
        
        return $result;
    }
    
    public static function modelsPk2Array($models, $field)
    {
        $result = array();
        foreach ($models as $aModel) {
            $arr                  = self::model2array($aModel);
            $result[$arr[$field]] = $arr;
        }
        
        return $result;
    }
    
    public static function modelsField2Array($models, $field, $vField = '')
    {
        $result = array();
        foreach ($models as $aModel) {
            $arr = self::model2array($aModel);
            if ($vField) {
                $result[$arr[$field]][] = $arr[$vField];
            }
            else {
                $result[$arr[$field]][] = $arr;
            }
        }
        
        return $result;
    }
    
    public static function models2Map($models, $pk = "id")
    {
        $result = array();
        foreach ($models as $aModel) {
            $arr         = self::model2array($aModel);
            $id          = $arr[$pk];
            $result[$id] = $arr;
        }
        
        return $result;
    }
    
    public static function selectField2Array($items, $field, $key = '', $isMany = 0)
    {
        $result = array();
        foreach ($items as $aItem) {
            if ($key) {
                if ($isMany) {
                    $result[$aItem[$key]][] = $aItem[$field];
                }
                else {
                    $result[$aItem[$key]] = $aItem[$field];
                }
            }
            else {
                $result[] = $aItem[$field];
            }
        }
        
        return $result;
    }
    
    public static function array2Array($items, $field, $isMany = 0)
    {
        $result = array();
        foreach ($items as $aItem) {
            if ($isMany) {
                $result[$aItem[$field]][] = $aItem;
            }
            else {
                $result[$aItem[$field]] = $aItem;
            }
        }
        
        return $result;
    }
    
    /**
     * 数组转对象
     * @param $array
     * @return StdClass
     */
    public static function array2object($arr)
    {
        if (gettype($arr) != 'array') {
            return;
        }
        foreach ($arr as $k => $v) {
            if (gettype($v) == 'array' || getType($v) == 'object') {
                $arr[$k] = (object)self::array2object($v);
            }
        }
        
        return (object)$arr;
    }
    
    /**
     * 对象转数组
     * @param $obj
     * @return mixed
     */
    public static function object_to_array($obj)
    {
        $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
        $arr  = [];
        foreach ($_arr as $key => $val) {
            $val       = (is_array($val) || is_object($val)) ? self::object_to_array($val) : $val;
            $arr[$key] = $val;
        }
        
        return $arr;
    }
    
    public static function string2Array($params)
    {
        $params = eval("return {$params};");
        
        return $params;
    }
    
    /**
     * 用 mb_strimwidth 来截取字符，使中英尽量对齐。
     * @param string $str
     * @param int    $start
     * @param int    $width
     * @param string $trimmarker
     * @return string
     */
    public static function wsubstr($str, $start, $width, $trimmarker = '...')
    {
        $_encoding = mb_detect_encoding($str, array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5'));
        
        return mb_strimwidth($str, $start, $width, $trimmarker, $_encoding);
    }
    
    ////////////////////////////////////////////////////////////////////
    // PHP截取中英文及标点符号混合的字符串函数（绝对不会出现乱码）
    // 本程序在utf-8、gb2312中测试通过。使用者自行测试big5。
    // 函数 left( 源字符串, 截取指定的字符串个数, 编码（可省略，默认为utf-8） )
    ////////////////////////////////////////////////////////////////////
    
    public static function rsubstr($str, $len, $charset = "utf-8")
    {
        //如果截取长度小于等于0，则返回空
        if (!is_numeric($len) or $len <= 0) {
            return "";
        }
        
        //如果截取长度大于总字符串长度，则直接返回当前字符串
        $sLen = strlen($str);
        if ($len >= $sLen) {
            return $str;
        }
        
        //判断使用什么编码，默认为utf-8
        if (strtolower($charset) == "utf-8") {
            $len_step = 3; //如果是utf-8编码，则中文字符长度为3
        }
        else {
            $len_step = 2; //如果是gb2312或big5编码，则中文字符长度为2
        }
        
        //执行截取操作
        $len_i = 0;
        //初始化计数当前已截取的字符串个数，此值为字符串的个数值（非字节数）
        $substr_len = 0; //初始化应该要截取的总字节数
        
        for ($i = 0; $i < $sLen; $i++) {
            if ($len_i >= $len) break; //总截取$len个字符串后，停止循环
            //判断，如果是中文字符串，则当前总字节数加上相应编码的中文字符长度
            if (ord(substr($str, $i, 1)) > 0xa0) {
                $i          += $len_step - 1;
                $substr_len += $len_step;
            }
            else { //否则，为英文字符，加1个字节
                $substr_len++;
            }
            $len_i++;
        }
        $result_str = substr($str, 0, $substr_len);
        
        return $result_str;
    }
    
    public static function sayErrors($model)
    {
        $errorMsg = "";
        $errors   = $model->getErrors();
        
        foreach ($errors as $field => $error) {
            $msg      = implode(", ", $error);
            $errorMsg .= "{$field}:{$msg}";
        }
        
        return $errorMsg;
    }
    
    public static function walkArr(&$item, $key, $replace)
    {
        $item = str_replace($replace, '', $item);
    }
    
    /**
     * 按行数和字符数截取html
     * @param S $string  html字符串
     * @param I $maxRow  最大行数
     * @param I $maxChar 每行最多中文字数
     * @param I $ratio   每个中文字相当于多少个英文字符
     */
    public static function cutHtmlByRowAndCharNum($string, $maxRow, $maxChar, $ratio = 1)
    {
        $parts    = preg_split('/(<\/?[a-z].*?>)/is', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
        $num      = 0;
        $maxBytes = $maxChar * $ratio;
        
        $preHtmlTag = '';
        foreach ($parts as $k => $v) {
            if ($num >= $maxRow) {
                $parts[$k] = '';
            }
            if (in_array($v, array('<br />', '</p>', '<br>'))) {
                if ($v == '</p>' && in_array($preHtmlTag, array('<br />', '<br>'))) {
                    $num += 0;
                }
                else {
                    $num += 1;
                }
            }
            elseif ($v[0] != '<') {
                $vDecode = htmlspecialchars_decode($v);
                $byteNum = $ratio == 1 ? mb_strlen($vDecode, 'utf-8') : self::getStringBytes($vDecode, $ratio);
                if ($byteNum > $maxBytes) {
                    $rowsInText = ceil($byteNum / $maxBytes);
                    if ($num < $maxRow) {
                        if (($num + $rowsInText) > $maxRow) {
                            $parts[$k] = $ratio == 1 ? mb_strcut($vDecode, 0, ($maxRow - $num) * $maxChar * 3, 'utf-8') : self::cutString($vDecode, ($maxRow - $num) * $maxBytes, $ratio);
                        }
                    }
                    $num += $rowsInText - 1;
                }
            }
            $preHtmlTag = $v;
        }
        $moreThanMax = $num > $maxRow;
        
        return array('more' => $moreThanMax, 'string' => implode('', $parts));
    }
    
    //表情替换
    public static function translateQingGuoHbbSmilie($text)
    {
        $smilie     = GXSmilie::getQingGuoHbbSmilie();
        $aSmilie    = array_combine($smilie[0], $smilie[1]);
        $aSmilieImg = array();
        foreach ($aSmilie as $key => $v) {
            $aSmilieImg[$key] = '<img width="24" height="24" title="' . rtrim(ltrim($key, '['), ']') . '" src="http://jic.qingguo.com/www/i/smiley/' . $v . '">';
        }
        $content = str_replace($smilie[0], $aSmilieImg, $text);
        
        return $content;
    }
    
    public static function getFormatPrice($price)
    {
        return number_format($price, 0, ".", "");
    }
    
    public static function processUserAge($date)
    {
        $result = '未知';
        if ($date) {
            $nowYear = date('Y');
            $oldYear = date('Y', strtotime($date));
            $result  = $nowYear - $oldYear;
        }
        
        return $result;
    }
    
    
    //替换字符串$string中指定的html标签$tag
    //返回过滤后的字符串
    /*
    *$param $string  要过滤的字符串  字符串
    *$param $tags   被审查的html标签 数组或单个字符串标签
    *$param $replace 被替换后的字符串  字符串
    */
    public static function replaceTags($string, $tags = 'a', $replace = "")
    {
        if (empty($string) || !is_string($string)) {
            return $string;
        }
        if (!is_array($tags)) {
            $tags = array($tags);
        }
        foreach ($tags as $key => $value) {
            $tag    = array("/<" . $value . "[\s\S]*>/iU", "/<\/" . $value . ">/iU");
            $string = preg_replace($tag, $replace, $string);
        }
        
        return $string;
    }
    
    public static function turnString($data, $val)
    {
        $result = "";
        if (isset($data[$val]) && (is_string($data[$val]) || is_int($data[$val]))) {
            $result = $data[$val];
        }
        
        return $result;
    }
    
    //这个星期的星期一
    //@$timestamp，某个星期的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    public static function thisMonday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $monday_date = date('Y-m-d', $timestamp - 86400 * date('w', $timestamp) + (date('w', $timestamp) > 0 ? 86400 : -/*6*86400*/518400));
        if ($is_return_timestamp) {
            $time = strtotime($monday_date);
        }
        else {
            $time = $monday_date;
        }
        
        return $time;
    }
    
    //这个星期的星期天
    //@$timestamp，某个星期的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    public static function thisSunday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $sunday = self::thisMonday($timestamp) +/*6*86400*/
            518400;
        if ($is_return_timestamp) {
            $time = $sunday;
        }
        else {
            $time = date('Y-m-d', $sunday);
        }
        
        return $time;
    }
    
    //上周一
    //@$timestamp，某个星期的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    public static function lastMonday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $thismonday = self::thisMonday($timestamp) -/*7*86400*/
            604800;
        if ($is_return_timestamp) {
            $time = $thismonday;
        }
        else {
            $time = date('Y-m-d', $thismonday);
        }
        
        return $time;
    }
    
    //上个星期天
    //@$timestamp，某个星期的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    public static function lastSunday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $thissunday = self::thisSunday($timestamp) -/*7*86400*/
            604800;
        if ($is_return_timestamp) {
            $time = $thissunday;
        }
        else {
            $time = date('Y-m-d', $thissunday);
        }
        
        return $time;
    }
    
    //下周一
    //@$timestamp，某个星期的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    public static function nextMonday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $thismonday = self::thisMonday($timestamp) +/*7*86400*/
            604800;
        if ($is_return_timestamp) {
            $time = $thismonday;
        }
        else {
            $time = date('Y-m-d', $thismonday);
        }
        
        return $time;
    }
    
    //下个星期天
    //@$timestamp，某个星期的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    public static function nextSunday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $thissunday = self::thisSunday($timestamp) +/*7*86400*/
            604800;
        if ($is_return_timestamp) {
            $time = $thissunday;
        }
        else {
            $time = date('Y-m-d', $thissunday);
        }
        
        return $time;
    }
    
    //这个月的第一天
    //@$timestamp，某个月的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    
    public static function monthFirstday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $firstday = date('Y-m-d', mktime(0, 0, 0, date('m', $timestamp), 1, date('Y', $timestamp)));
        if ($is_return_timestamp) {
            $time = strtotime($firstday);
        }
        else {
            $time = $firstday;
        }
        
        return $time;
    }
    
    //这个月的最后一天
    //@$timestamp，某个月的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    
    public static function monthLastday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $lastday = date('Y-m-d', mktime(0, 0, 0, date('m', $timestamp), date('t', $timestamp), date('Y', $timestamp)));
        if ($is_return_timestamp) {
            $time = strtotime($lastday);
        }
        else {
            $time = $lastday;
        }
        
        return $time;
    }
    
    //上个月的第一天
    //@$timestamp，某个月的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    
    public static function lastmonthFirstday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $firstday = date('Y-m-d', mktime(0, 0, 0, date('m', $timestamp) - 1, 1, date('Y', $timestamp)));
        if ($is_return_timestamp) {
            $time = strtotime($firstday);
        }
        else {
            $time = $firstday;
        }
        
        return $time;
    }
    
    //上个月的最后一天
    //@$timestamp，某个月的某一个时间戳，默认为当前时间
    //@is_return_timestamp,是否返回时间戳，否则返回时间格式
    
    public static function lastmonthLastday($timestamp = 0, $is_return_timestamp = true)
    {
        $time = 0;
        if (!$timestamp) {
            $timestamp = time();
        }
        $lastday = date('Y-m-d', mktime(0, 0, 0, date('m', $timestamp) - 1, date('t', self::lastmonthFirstday($timestamp)), date('Y', $timestamp)));
        if ($is_return_timestamp) {
            $time = strtotime($lastday);
        }
        else {
            $time = $lastday;
        }
        
        return $time;
    }
    
    /**
     * 获取文件行数
     */
    public static function getFileLineNum($filePath)
    {
        $line = 0; //初始化行数
        if (file_exists($filePath)) {
            //打开文件
            $fp = fopen($filePath, 'r') or die("open file failure!");
            if ($fp) {
                //获取文件的一行内容，注意：需要php5才支持该函数；
                while (stream_get_line($fp, 8192, "\n")) {
                    $line++;
                }
                fclose($fp);//关闭文件
            }
        }
        
        return $line;
    }
    
    /**
     * 获取来源 （android，ios，PC）
     * @return <int> 1:android,2:ios,0:默认
     */
    public static function getSource()
    {
        $agent = strtolower($_SERVER['HTTP_USER_AGENT']);
        // $is_pc      = (strpos($agent, 'windows nt')!=false) ? true : false;
        // $is_mac     = (strpos($agent, 'macintosh')!=false) ? true : false;
        // $is_ubt     = (strpos($agent, 'x11')!=false) ? true : false;
        $is_iphone  = (strpos($agent, 'iphone') != false) ? true : false;
        $is_ipad    = (strpos($agent, 'ipad') != false) ? true : false;
        $is_android = (strpos($agent, 'android') != false) ? true : false;
        $is_ios     = (strpos($agent, 'ios') != false) ? true : false;
        $is_adr     = (strpos($agent, 'adr') != false) ? true : false;
        $source     = 0;
        if ($is_android || $is_adr) {
            $source = 1;
        }
        elseif ($is_iphone || $is_ipad || $is_ios) {
            $source = 2;
        }
        else {
            $source = 0;
        }
        
        return $source;
    }
    
    /**
     * 获得字符串字节数
     * @param S $str
     * @param I $rate
     */
    public static function getStringBytes($str, $rate = 2)
    {
        $count  = $n = 0;
        $strlen = strlen($str);
        while ($n < $strlen) {
            $currentByte = ord(substr($str, $n, 1));
            $incre       = 194 <= $currentByte && $currentByte <= 223 ? 2 :
                224 <= $currentByte && $currentByte <= 253 ? 3 : 1;
            $countIncre  = $incre > 1 ? $rate : 1;
            $n           = $n + $incre;
            $count       = $count + $countIncre;
        }
        
        return $count;
    }
    
    /**
     * 合并两个或多个数组到一个递归.
     * @param array $a array to be merged to
     * @param array $b array to be merged from. You can specify additional
     *                 arrays via third argument, fourth argument etc.
     * @return array the merged array (the original arrays are not changed.)
     * @see mergeWith
     */
    public static function mergeArray($a, $b)
    {
        $args = func_get_args();
        $res  = array_shift($args);
        while (!empty($args)) {
            $next = array_shift($args);
            foreach ($next as $k => $v) {
                if (is_integer($k))
                    isset($res[$k]) ? $res[] = $v : $res[$k] = $v;
                elseif (is_array($v) && isset($res[$k]) && is_array($res[$k]))
                    $res[$k] = self::mergeArray($res[$k], $v);
                else
                    $res[$k] = $v;
            }
        }
        
        return $res;
    }
    
    /**
     * 加密
     * @param $str 字符串
     * @param $key 密钥
     * @author lishuaichen
     */
    public static function encrypt($str, $key)
    {
        $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, trim($str), MCRYPT_MODE_ECB);
        $data      = base64_encode($encrypted);
        
        return $data;
    }
    
    /**
     * 解密
     * @param $str 加密后的字符串
     * @param $key 密钥
     * @author lishuaichen
     */
    public static function decrypt($str, $key)
    {
        $encryptedData = base64_decode($str);
        $data          = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encryptedData, MCRYPT_MODE_ECB);
        
        return trim($data);
    }
    
    /**
     * 获取ip地址
     */
    public static function getIP()
    {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) {
            $ip = getenv("HTTP_CLIENT_IP");
        }
        else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        }
        else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) {
            $ip = getenv("REMOTE_ADDR");
        }
        else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        else {
            $ip = "1";
        }
        
        return $ip;
    }
    
    /**
     * 获取唯一ID
     */
    public static function uniq_id()
    {
        return uniqid(ip2long(self::getIP()) . '_');
    }
    
    // 文本信息简单加密
    public static function encodeText($text)
    {
        if ($text === '') {
            return $text;
        }
        
        $base64 = base64_encode($text);
        $length = ord($base64[0]) % 10 + 3;
        $rand   = self::randomStr($length);
        $code   = substr($base64, 0, 1) . $rand . substr($base64, 1);
        
        return $code;
    }
    
    // 文本信息简单解密
    public static function decodeText($text)
    {
        if (strlen($text) <= 1) {
            return $text;
        }
        $key  = substr($text, 0, 1);
        $num  = ord($key) % 10 + 3;
        $code = substr($text, 0, 1) . substr($text, 1 + $num);
        
        return base64_decode($code);
    }
    
    /**
     * 生成随机数
     */
    public static function randomStr($length, $chars = null)
    {
        $random = '';
        if (!$length || !is_numeric($length)) {
            return $random;
        }
        
        if (!$chars) {
            $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        }
        
        for ($i = 0; $i < $length; $i++) {
            $k      = rand(0, strlen($chars) - 1);
            $random .= $chars[$k];
        }
        
        return $random;
    }
    
    //随机从数组里取出多个值
    public static function getRandValues($data, $num)
    {
        $result = [];
        $index  = array_rand($data, $num);
        if (is_array($index)) {
            foreach ($index as $val) {
                $result[] = $data[$val];
            }
        }
        else {
            $result[] = $data[$index];
        }
        
        return $result;
    }
    
    //过滤空格
    public static function myTrim($str)
    {
        $search  = array(" ", "　");
        $replace = array("", "");
        
        return str_replace($search, $replace, $str);
    }
    
    /**
     * 环境域名加前辍
     * @author pengshiwen
     * @date   2018-01-20
     */
    public static function envUrl($url)
    {
        //生产环境或测试环境
        if (defined("PRODUCT_ENV") && PRODUCT_ENV) return $url;
        if (!$url || !is_string($url)) return '';
        $env = '';
        //RELEASE环境
        if (defined("RELEASE_ENV") && RELEASE_ENV) {
            $env = 'release-';
        }
        //QA环境
        if (defined("QA_ENV") && QA_ENV) {
            $env = 'qa-';
        }
        //灰度环境
        if (defined("GRAY_RELEASE_ENV") && GRAY_RELEASE_ENV) {
            $env = 'dev-hui-';
        }
        //测试环境
        if (defined("INTEGRATED_ENV") && INTEGRATED_ENV) {
            $env = 'dev-';
        }
        //本地环境
        if (defined("LOCAL_ENV") && LOCAL_ENV) {
            $env = 'local-';
        }
        $url = str_replace('http://', 'http://' . $env, $url, $count);
        if ($count) return $url;
        $url = str_replace('https://', 'https://' . $env, $url, $count);
        if ($count) return $url;
        
        return $env . $url;
    }
    
    /**
     * replaceMobile 替换手机号中间4位为*
     * @param $mobile
     * @author yangminghui
     * @date   2018/5/26
     */
    public static function replaceMobile($mobile)
    {
        return substr($mobile, 0, 3) . '****' . substr($mobile, -4, 4);
    }
    
    /**
     * 获取环境
     * @return string
     * @author yangminghui
     * @date   2018/10/13
     */
    public static function getEnvName()
    {
        // TODO 2018年10月17日14:48:11 去除线上环境标识
        $env = PRODUCT_ENV ? '' : (GRAY_RELEASE_ENV ? '【灰度环境】：' : '【测试环境】：');
        
        return $env;
    }
    
    /**
     * @name 获取比例
     * @param int  $numerator   分子
     * @param int  $denominator 分母
     * @param bool $denominator 是否取整 0 直接截取  1 四舍五入 2 向上取整 3 向下取整
     * @param int  $denominator 小数位数
     */
    public static function get_percent($numerator, $denominator, $is_int = 0, $decimals = 0)
    {
        if ($numerator == 0 || $denominator == 0) {
            $percent = 0;
        }
        else {
            $percent = $numerator * 100 / $denominator;
        }
        if ($decimals < 0 || !in_array($is_int, [0, 1, 2, 3])) {
            return false;
        }
        switch ($is_int) {
            case 0:
                $percent = self::cut_decimal($percent, $decimals);
                break;
            case 1:
                $percent = self::cut_decimal(round($percent), $decimals);
                break;
            case 2:
                $percent = self::cut_decimal(ceil($percent), $decimals);
                break;
            case 3:
                $percent = self::cut_decimal(floor($percent), $decimals);
                break;
            default:
                // 直接截取
                $percent = self::cut_decimal($percent, $decimals);
                break;
        }
        
        return $percent . '%';
    }
    
    public static function cut_decimal($decimal, $len)
    {
        $format = '%.' . ($len + 1) . 'f';
        
        return substr(sprintf($format, $decimal), 0, $len == 0 ? -2 : -1);
    }
    
    /**
     * 获取当前季节
     * @return int  季节
     * @author yangminghui
     * @date   2018/11/6
     */
    public static function get_season()
    {
        // 当前时间
        $month  = date('m');
        $season = 0;
        // 当前月份
        if ($month > 0 && $month < 3) {
            $season = 4;// 寒季
        }
        if ($month > 2 && $month < 7) {
            $season = 1;// 春季
        }
        if ($month > 6 && $month < 9) {
            $season = 2;// 暑季
        }
        if ($month > 8 && $month < 13) {
            $season = 3;// 秋季
        }
        
        return $season;
    }
    
    /**
     * 提取字符串中的数字
     * @param string $str
     * @return string
     */
    public static function findNum($str = '')
    {
        $str = trim($str);
        
        if (empty($str)) {
            return '';
        }
        
        $temp   = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0');
        $result = '';
        
        for ($i = 0; $i < strlen($str); $i++) {
            if (in_array($str[$i], $temp)) {
                $result .= $str[$i];
            }
        }
        
        return $result;
    }
    
    /**
     * Passport 加密函数
     * @param string          等待加密的原字串
     * @param string          私有密匙(用于解密和加密)
     * @return               string          原字串经过私有密匙加密后的结果
     */
    public static function passport_encrypt($txt)
    {
        $txt = (String)$txt;
        // 使用随机数发生器产生 0~64000 的值并 MD5()
        
        $encrypt_key = md5(rand(0, 64000));
        
        // 变量初始化
        $ctr = 0;
        $tmp = '';
        
        // for 循环，$i 为从 0 开始，到小于 $txt 字串长度的整数
        for ($i = 0; $i < strlen($txt); $i++) {
            // 如果 $ctr = $encrypt_key 的长度，则 $ctr 清零
            
            $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
            
            // $tmp 字串在末尾增加两位，其第一位内容为 $encrypt_key 的第 $ctr 位，
            // 第二位内容为 $txt 的第 $i 位与 $encrypt_key 的 $ctr 位取异或。然后 $ctr = $ctr + 1
            
            $tmp .= $encrypt_key[$ctr] . ($txt[$i] ^ $encrypt_key[$ctr++]);
        }
        
        // 返回结果，结果为 passport_key() 函数返回值的 base64 编码结果
        
        return base64_encode(self::passport_key($tmp));
    }
    
    /**
     * Passport 解密函数
     * @param string          加密后的字串
     * @param string          私有密匙(用于解密和加密)
     * @return               string          字串经过私有密匙解密后的结果
     */
    public static function passport_decrypt($txt)
    {
        // $txt 的结果为加密后的字串经过 base64 解码，然后与私有密匙一起，
        // 经过 passport_key() 函数处理后的返回值
        
        $txt = self::passport_key(base64_decode($txt));
        
        // 变量初始化
        $tmp = '';
        
        // for 循环，$i 为从 0 开始，到小于 $txt 字串长度的整数
        
        for ($i = 0; $i < strlen($txt); $i++) {
            // $tmp 字串在末尾增加一位，其内容为 $txt 的第 $i 位，
            // 与 $txt 的第 $i + 1 位取异或。然后 $i = $i + 1
            
            $tmp .= $txt[$i] ^ $txt[++$i];
        }
        
        // 返回 $tmp 的值作为结果
        
        return $tmp;
        
    }
    
    /**
     * Passport 密匙处理函数
     * @param string          待加密或待解密的字串
     * @param string          私有密匙(用于解密和加密)
     * @return               string          处理后的密匙
     */
    private static function passport_key($txt, $encrypt_key = 'limikeji')
    {
        $encrypt_key = self::getKey($encrypt_key);
        // 将 $encrypt_key 赋为 $encrypt_key 经 md5() 后的值
        
        $encrypt_key = md5($encrypt_key);
        
        // 变量初始化
        $ctr = 0;
        $tmp = '';
        
        // for 循环，$i 为从 0 开始，到小于 $txt 字串长度的整数
        
        for ($i = 0; $i < strlen($txt); $i++) {
            // 如果 $ctr = $encrypt_key 的长度，则 $ctr 清零
            
            $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
            
            // $tmp 字串在末尾增加一位，其内容为 $txt 的第 $i 位，
            // 与 $encrypt_key 的第 $ctr + 1 位取异或。然后 $ctr = $ctr + 1
            
            $tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
        }
        
        // 返回 $tmp 的值作为结果
        
        return $tmp;
    }
    
    public static function getKey($key)
    {
        // 灰度
        if (PRODUCT_ENV) {
            $key = 'product:' . $key;
        }
        // 灰度
        if (GRAY_RELEASE_ENV) {
            $key = 'gray:' . $key;
        }
        // release
        if (RELEASE_ENV) {
            $key = 'release:' . $key;
        }
        // qa
        if (QA_ENV) {
            $key = 'qa:' . $key;
        }
        // 测试
        if (DEV_ENV) {
            $key = 'dev:' . $key;
        }
        // 本地
        if (LOCAL_ENV) {
            $key = 'local:' . $key;
        }
        
        return $key;
    }
}
